
package edu.csu.smartpark.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONCreator;
import edu.csu.smartpark.model.DO.*;
import edu.csu.smartpark.model.DTO.ChargeOrderDTO;
import edu.csu.smartpark.model.DTO.TollMonthCardOrderDTO;
import edu.csu.smartpark.model.DTO.TollMonthCardProductDTO;
import edu.csu.smartpark.model.DTO.TollMonthCardProductQueryDTO;
import edu.csu.smartpark.model.PO.ParkingRecordPO;
import edu.csu.smartpark.model.PO.TollIotDetailPO;
import edu.csu.smartpark.model.PO.TollMonthCardOrderPO;
import edu.csu.smartpark.model.PO.TollMonthCardProductPO;
import edu.csu.smartpark.model.VO.*;
import edu.csu.smartpark.model.common.BusinessException;
import edu.csu.smartpark.model.common.MsgEntity;
import edu.csu.smartpark.service.OrderService;
import edu.csu.smartpark.service.ParkingService;
import edu.csu.smartpark.util.CommonUtil;
import edu.csu.smartpark.util.RequestUtil;
import edu.csu.smartpark.util.StringUtil;
import edu.csu.smartpark.util.JwtUtil;
import io.jsonwebtoken.Claims;
import jdk.internal.dynalink.support.NameCodec;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.spring.web.json.Json;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
@RequestMapping("/parking")
public class ParkingController {

    @Autowired
    ParkingService parkingService;

    @Autowired
    OrderService orderService;

    @Autowired
    private JwtUtil jwtUtil;
    /**
     * 设备绑定
     * @param spaceId
     * @param deviceId
     * @return
     */
    @PostMapping("/device/bind")
    public MsgEntity bingParking(String spaceId,String deviceId){
        return new MsgEntity("success",MsgEntity.SUCCESS,"绑定成功");
    }

    /**
     * 将设备解绑
     * @param spaceId
     * @param deviceId
     * @return
     */
    @GetMapping("/device/unbind")
    public MsgEntity unbindParking(String spaceId,String deviceId){
        if(spaceId == null || deviceId == null){
            return new MsgEntity("fail",MsgEntity.FAIL,"space id and device id can not be empty");
        }
        parkingService.unbindParkingDevice(spaceId,deviceId);
        return new MsgEntity("success",MsgEntity.SUCCESS,"解绑成功") ;

//        if (spaceId == null || spaceId.isEmpty()){
//            return new MsgEntity("fail", MsgEntity.FAIL, "space id can not be empty");
//        }
//        parkingService.deleteParkingQRCode(spaceId);
//        return new MsgEntity("success", MsgEntity.SUCCESS, "删除成功");
    }

    /**
     *
     * @return
     */
    @PostMapping("/car/access_records/query")
    public MsgEntity VehicleAccessRecordQuery(@RequestBody JSONObject params){
        String id = params.getString("id");
        String license = params.getString("license");
        String parkId = params.getString("parId");
        int vehicleState = params.getInteger("vehicleState");
        int vehicleType = params.getInteger("vehicleType");
        Date startTime = params.getDate("startTime");
        int status = params.getInteger("status");
        Date endTime = params.getDate("endTime");
        ParkingRecordQueryDO parkingRecordQueryDO = new ParkingRecordQueryDO();
        parkingRecordQueryDO.setId(id);
        parkingRecordQueryDO.setLicense(license);
        parkingRecordQueryDO.setParkId(parkId);
        parkingRecordQueryDO.setStatus(status);
        parkingRecordQueryDO.setVehicleType(vehicleType);
        parkingRecordQueryDO.setVehicleState(vehicleState);
        parkingRecordQueryDO.setStartTime(startTime);
        parkingRecordQueryDO.setEndTime(endTime);
        List<ParkingRecordPO>parkingRecordQueryPOS = parkingService.getParkingRecordQueryDO(parkingRecordQueryDO);
        return new MsgEntity("success",MsgEntity.SUCCESS,parkingRecordQueryPOS);

    }

    /**
     *4. 查看用户月卡接口
     * @param request
     * @return
     */
    @GetMapping("/monthly_card/query")
    public MsgEntity ViewUserMonthlyCardByUserId(HttpServletRequest request,@RequestParam JSONObject params) throws BusinessException {
        String jwtToken = request.getHeader("Authorization");
        Claims claims = jwtUtil.decode(jwtToken);
        String userIdOfMonthCard = (String)claims.get("userId");
        String userId = params.getString("userId");
        String Id = params.getString("Id");
        String license = params.getString("license");
        String parkId = params.getString("parkId");
        int status = params.getInteger("status");
        int pageNum = (int)params.getOrDefault("pageNum", 1);
        int pageSize = (int)params.getOrDefault("pageSize", 10);

        if(userIdOfMonthCard == null){
            userIdOfMonthCard = userId;
        }
        //通过userId查询月卡记录,这里认为userid就是buyId
        TollMonthCardQueryDO tollMonthCardQueryDO = new TollMonthCardQueryDO();
        tollMonthCardQueryDO.setBuyerId(userIdOfMonthCard);
        tollMonthCardQueryDO.setLicense(license);
        tollMonthCardQueryDO.setStatus(status);
        tollMonthCardQueryDO.setParkId(parkId);
        tollMonthCardQueryDO.setId(Id);
        PageVO<TollMonthCardDO>monthCardPage = parkingService.getTollMonthCardList(pageNum,pageSize,tollMonthCardQueryDO);
        return new MsgEntity("success",MsgEntity.SUCCESS,monthCardPage);
    }

    @PostMapping("/monthly_card_product/create")
    public MsgEntity createMonthlyCardProduct(@RequestBody @Validated TollMonthCardProductDTO tollMonthCardProductDTO) throws BusinessException{
        //参数校验
        if(tollMonthCardProductDTO == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"parameter bind error");
        }
        if(tollMonthCardProductDTO.getCardName().equals("")){
            return new MsgEntity("success",MsgEntity.SUCCESS,"cardName can not be null");
        }
        if(tollMonthCardProductDTO.getMonthlyFee() == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"MonthlyFee can not be null");
        }
        if(tollMonthCardProductDTO.getAvailableCarType() == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"AvailableCarType can not be empty");
        }
        if(tollMonthCardProductDTO.getStatus() == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"status can not be empty");
        }
        if(tollMonthCardProductDTO.getParkId() == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"parkid can not be empty");
        }
        if(tollMonthCardProductDTO.getBriefIntroduction() == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"BriefIntroduction can not be empty");
        }
        if(tollMonthCardProductDTO.getAvailableTime() == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"AvailableTime can not be empty");
        }
        TollMonthCardProductDO tollMonthCardProductDO = new TollMonthCardProductDO();
        BeanUtils.copyProperties(tollMonthCardProductDTO,tollMonthCardProductDO);
        String productId = parkingService.creatTollMonthProduct(tollMonthCardProductDO);
        return new MsgEntity("success",MsgEntity.SUCCESS,productId);
    }

    @PostMapping("/monthly_card_product/update")
    public MsgEntity modifyTollMonthCardProduct(@RequestBody JSONObject params) throws BusinessException{
        String productId = params.getString("productId");
        String cardName = params.getString("cardName");
        String briefIntroduction = params.getString("briefIntroduction");
        Integer availableCarType = params.getInteger("availableCarType");
        Integer availableTime = params.getInteger("availableTime");
        String parkId = params.getString("parkId");
        Double monthlyFee = params.getDouble("monthlyFee");
        Integer status = params.getInteger("status");
        if(productId == null || productId.equals("")){
            return new MsgEntity("success",MsgEntity.SUCCESS,"productId can not be empty");
        }
        TollMonthCardProductDO tollMonthCardProductDO = new TollMonthCardProductDO();
        tollMonthCardProductDO.setCardName(cardName);
        tollMonthCardProductDO.setParkId(parkId);
        tollMonthCardProductDO.setStatus(status);
        tollMonthCardProductDO.setId(productId);
        tollMonthCardProductDO.setMonthlyFee(monthlyFee);
        tollMonthCardProductDO.setAvailableCarType(availableCarType);
        tollMonthCardProductDO.setAvailableTime(availableTime);
        tollMonthCardProductDO.setBriefIntroduction(briefIntroduction);
        parkingService.updateTollMonthProduct(tollMonthCardProductDO);
        return new MsgEntity("success",MsgEntity.SUCCESS,"update space info success");
    }

    //7. 月卡商品查询接口
    @PostMapping("/monthly_card_product/query")
    public MsgEntity getTollMonthCardProduct(@RequestBody JSONObject params){
        String productId = params.getString("productId");
        String cardName = params.getString("");
        Integer availableCarType = params.getInteger("availableCarType");
        Integer availableTime = params.getInteger("availableTime");
        String parkId = params.getString("parkId");
        Integer status = params.getInteger("status");
        int pageNum = (int)params.getOrDefault("pageNum", 1);
        int pageSize = (int)params.getOrDefault("pageSize", 10);
        TollMonthCardProductQueryDTO tollMonthCardProductQueryDTO = new TollMonthCardProductQueryDTO();
        tollMonthCardProductQueryDTO.setProductId(productId);
        tollMonthCardProductQueryDTO.setCardName(cardName);
        tollMonthCardProductQueryDTO.setParkId(parkId);
        tollMonthCardProductQueryDTO.setAvailableCarType(availableCarType);
        tollMonthCardProductQueryDTO.setStatus(status);
        tollMonthCardProductQueryDTO.setAvailableTime(availableTime);
        PageVO<TollMonthCardProductDO> tollMonthCardProductDOPage = parkingService.getTollMonthCardProductList(pageNum,pageSize,tollMonthCardProductQueryDTO);
        return new MsgEntity("success",MsgEntity.SUCCESS,tollMonthCardProductDOPage);
    }

    //8. 月卡商品删除接口
    @GetMapping("/monthly_card_product/delete")
    public MsgEntity removeMonthCardProduct(String productId){
        if(productId == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"产品ID不能为空");
        }
        parkingService.removeMonthCardProduct(productId);
        return new MsgEntity("success",MsgEntity.SUCCESS,"删除月卡商品成功");
    }

    //9. 停车收费订单订单查询接口
    @PostMapping("/charge_order/query")
    public MsgEntity queryChargeOrder(@RequestBody @Validated ChargeOrderDTO chargeOrderDTO){
        PageVO<ChargeOrderVO>chargeOrderVOPageVO = new PageVO<>();
        chargeOrderVOPageVO = parkingService.getChargeOrderList(chargeOrderDTO);
        if(chargeOrderVOPageVO == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"error");
        }
        return new MsgEntity("success",MsgEntity.SUCCESS,chargeOrderVOPageVO);
    }

    //10. 月卡充值订单查询接口
    @PostMapping("/month_card_recharge_order/query")
    public MsgEntity queryMonthCardRechargeOrder(@RequestBody JSONObject params){
        int pageNum = (int)params.getOrDefault("pageNum", 1);
        int pageSize = (int)params.getOrDefault("pageSize", 10);
        String orderId = params.getString("orderId");
        String license = params.getString("license");
        Integer orderType = params.getInteger("orderType");
        String buyerId = params.getString("buyerId");
        String startTime = params.getString("startTime");
        String endTime = params.getString("endTime");
        Integer status = params.getInteger("status");
        PageVO<TollMonthCardOrderPO>tollMonthCardOrderPOPageVO = parkingService.getTollMonthCardOrderPOList(orderId,pageSize,pageNum);

        return new MsgEntity("success",MsgEntity.SUCCESS,tollMonthCardOrderPOPageVO);
    }

    //11. 设备创建
    @PostMapping("/device/create")
    public MsgEntity createDevice(@RequestBody JSONObject params) throws BusinessException{
        String deviceName = params.getString("deviceName");
        String deviceId = params.getString("deviceId");
        TollIotDetailPO tollIotDetailPO = new TollIotDetailPO();
        String deviceId1 = parkingService.createDevice(deviceId,deviceName);
        return new MsgEntity("success",MsgEntity.SUCCESS,deviceId1);
    }

    //12.设备修改
    @PostMapping("/device/update")
    public MsgEntity updateDevice(@RequestBody JSONObject params) throws BusinessException{
        String deviceName = params.getString("deviceName");
        String deviceId = params.getString("deviceId");
        parkingService.updateDevice(deviceId,deviceName);
        return new MsgEntity("success",MsgEntity.SUCCESS,"设备修改成功");
    }
    //13.设备删除
    @GetMapping("/device/remove")
    public MsgEntity removeDevice(String id){
        if(id == null){
            return new MsgEntity("success",MsgEntity.SUCCESS,"设备识别错误");
        }
        parkingService.removeDevice(id);
        return new MsgEntity("success",MsgEntity.SUCCESS,"设备删除成功");
    }

    //14. 设备查询
    public MsgEntity queryDeviceList(@RequestBody JSONObject params) throws BusinessException{
        int pageNum = (int)params.getOrDefault("pageNum", 1);
        int pageSize = (int)params.getOrDefault("pageSize", 10);
        PageVO<TollIotDetailVO>devicePage = parkingService.getDeviceList(pageSize,pageNum);

        return new MsgEntity("success",MsgEntity.SUCCESS,devicePage);
    }


    @GetMapping("/QRCode/create")
    public MsgEntity generateQRCode(String url){
        if (url == null || url.isEmpty()){
            return new MsgEntity("fail", MsgEntity.FAIL, "url can not be empty");
        }
        Map<String, String> urlParams = CommonUtil.URLAnalysis(url);
        String spaceId = urlParams.get("spaceId");
        String deviceId = urlParams.get("deviceId");
        if (spaceId == null || spaceId.equals("")) {
            return new MsgEntity("fail", MsgEntity.FAIL, "url lacks parameter spaceId");
        }
        if (deviceId == null || deviceId.equals("")){
            return new MsgEntity("fail", MsgEntity.FAIL, "url lacks parameter deviceId");
        }
        ParkingQRCodeDO parkingQRCodeDO = parkingService.generateParkingQRCode(url, spaceId, deviceId);
        ParkingQRCodeVO parkingQRCodeVO = new ParkingQRCodeVO();
        BeanUtils.copyProperties(parkingQRCodeDO, parkingQRCodeVO);
        return new MsgEntity("success", MsgEntity.SUCCESS,parkingQRCodeVO);
    }

    @GetMapping("/QRCode/get")
    public MsgEntity getQRCode(String spaceId) {
        if (spaceId == null || spaceId.isEmpty()){
            return new MsgEntity("fail", MsgEntity.FAIL, "space id can not be empty");
        }
        ParkingQRCodeDO parkingQRCodeDO = parkingService.getParkingQRCode(spaceId);
        ParkingQRCodeVO parkingQRCodeVO = new ParkingQRCodeVO();
        BeanUtils.copyProperties(parkingQRCodeDO, parkingQRCodeVO);
        return new MsgEntity("success", MsgEntity.SUCCESS,parkingQRCodeVO);
    }

    @GetMapping("/QRCode/delete")
    public MsgEntity deleteQRCode(String spaceId){
        if (spaceId == null || spaceId.isEmpty()){
            return new MsgEntity("fail", MsgEntity.FAIL, "space id can not be empty");
        }
        parkingService.deleteParkingQRCode(spaceId);
        return new MsgEntity("success", MsgEntity.SUCCESS, "删除成功");
    }

    @PostMapping("/entrance/plate/receiver")
    public JSONObject parkingEntrancePlateReceiver(@RequestBody JSONObject params){
        LicensePlateResultDO licensePlateResultDO = parseLicensePlateResultJson(params);
        LicensePlateResultVO licensePlateResultVO = new LicensePlateResultVO();
        // 判断车辆是否拥有进场权限
        if (StringUtil.isEmpty(licensePlateResultDO.getLicense()) || !parkingService.isAllowedEntry(licensePlateResultDO.getLicense())){
            // TODO LED灯显示无法入场
            licensePlateResultVO.setInfo("no");
            licensePlateResultVO.setPlateId(licensePlateResultDO.getPlateId());
            return makeLicensePlateResultResponse(licensePlateResultVO);
        }
        // 存储车辆进场信息
        ParkingRecordDO parkingRecordDO = new ParkingRecordDO();
        BeanUtils.copyProperties(licensePlateResultDO, parkingRecordDO);
        parkingRecordDO.setVehicleState(1);
        parkingRecordDO.setEntryTime(licensePlateResultDO.getReceivedTime());
        parkingRecordDO.setEntryPictureUrl(licensePlateResultDO.getSnapImageUrl());
        TollIotDetailDO tollIotDetailDO = parkingService.getTollIotDetailDO(licensePlateResultDO.getDeviceId());
        parkingRecordDO.setEntrySpaceId(tollIotDetailDO.getSpaceId());
        parkingRecordDO.setEntrySpaceName(tollIotDetailDO.getSpaceName());
        parkingRecordDO.setParkId(tollIotDetailDO.getParkId());
        parkingRecordDO.setStatus(0);
        parkingService.createParkingRecord(parkingRecordDO);
        // 返回指令，允许开闸
        licensePlateResultVO.setInfo("ok");
        licensePlateResultVO.setPlateId(licensePlateResultDO.getPlateId());
        return makeLicensePlateResultResponse(licensePlateResultVO);
    }

    @PostMapping("/exit/plate/receiver")
    public JSONObject parkingExitPlateReceiver(@RequestBody JSONObject params){
        LicensePlateResultDO licensePlateResultDO = parseLicensePlateResultJson(params);
        LicensePlateResultVO licensePlateResultVO = new LicensePlateResultVO();
        ParkingRecordDO exitParkingRecord = new ParkingRecordDO();
        ParkingRecordQueryDO parkingRecordQueryDO = new ParkingRecordQueryDO();
        // 查询此车辆的进场信息
        parkingRecordQueryDO.setLicense(licensePlateResultDO.getLicense());
        parkingRecordQueryDO.setVehicleState(1);
        List<ParkingRecordDO> parkingRecordDOs = parkingService.getParkingRecord(parkingRecordQueryDO);
        // 如果不存在进场信息
        if (parkingRecordDOs.size() == 0){
            // 没有前置进场信息，返回no, 人工处置开闸
            licensePlateResultVO.setInfo("no");
            licensePlateResultVO.setPlateId(licensePlateResultDO.getPlateId());
            return makeLicensePlateResultResponse(licensePlateResultVO);
        }
        ParkingRecordDO preEntranceParkingRecord = parkingRecordDOs.get(0);
        // 处理一个车辆查出多个入场信息的异常情况，取入场时间离现在最近的入场记录作为需要处理的对象
        for (ParkingRecordDO parkingRecord: parkingRecordDOs){
            if (preEntranceParkingRecord.getEntryTime().before(parkingRecord.getEntryTime())){
                preEntranceParkingRecord = parkingRecord;
            }
        }
        BeanUtils.copyProperties(preEntranceParkingRecord, exitParkingRecord);
        exitParkingRecord.setVehicleState(2);
        exitParkingRecord.setOutTime(licensePlateResultDO.getReceivedTime());
        exitParkingRecord.setOutPictureUrl(licensePlateResultDO.getSnapImageUrl());
        TollIotDetailDO tollIotDetailDO = parkingService.getTollIotDetailDO(licensePlateResultDO.getDeviceId());
        exitParkingRecord.setOutSpaceId(tollIotDetailDO.getSpaceId());
        exitParkingRecord.setOutSpaceName(tollIotDetailDO.getSpaceName());
        Date entryTime = exitParkingRecord.getEntryTime();
        Date outTime = exitParkingRecord.getOutTime();
        Integer parkingTime = (int)((outTime.getTime()- entryTime.getTime())/60000);
        exitParkingRecord.setParkingTime(parkingTime);
        // TODO 根据停车区域id获取收费标准，传入计费函数进行费用计算
        Double fee = parkingService.calculateParkingFee("",entryTime, outTime);
        exitParkingRecord.setTollFee(fee);

        // 判断车辆是否可以使用月卡支付
        boolean isMonthCardValid;
        TollMonthCardQueryDO tollMonthCardQueryDO = new TollMonthCardQueryDO();
        tollMonthCardQueryDO.setLicense(licensePlateResultDO.getLicense());
        List<TollMonthCardDO> tollMonthCardDOs = parkingService.getTollMonthCard(tollMonthCardQueryDO);
        if (tollMonthCardDOs.size() == 0){
            isMonthCardValid = false;
        } else {
            isMonthCardValid = parkingService.isTollMonthCardValid(tollMonthCardDOs.get(0), exitParkingRecord);
        }

        if (isMonthCardValid){
            exitParkingRecord.setPaymentType(tollMonthCardDOs.get(0).getCardName());
        } else {
            // 创建停车记录订单
            ParkingOrderDO parkingOrderDO = new ParkingOrderDO();
            parkingOrderDO.setInoutId(exitParkingRecord.getId());
            parkingOrderDO.setLicense(exitParkingRecord.getLicense());
            parkingOrderDO.setOrderTotal(fee);
            parkingOrderDO.setDiscountAmount(0.0);
            parkingOrderDO.setPayableAmount(fee);
            parkingOrderDO.setParkId(exitParkingRecord.getParkId());
            parkingOrderDO.setStatus(1);
            String orderId = orderService.createParkingOrder(parkingOrderDO);
            // 开启子线程查询订单是否已支付,主线程阻塞
            boolean isNormalReturn; //  是否正常返回，即判断订单已支付进行的返回
            FutureTask<Boolean> parkingOrderStatusQuery = new FutureTask<>(new Callable<Boolean>() {
                        @Override
                        public Boolean call() throws Exception {
                            try {
                                while (true){
                                    if (orderService.isParkingOrderPay(orderId))
                                        return true;
                                    Thread.sleep(3000);
                                }
                            }catch (InterruptedException e){
                                return false;
                            }
                        }
                    }
            );
            Thread t = new Thread(parkingOrderStatusQuery);
            t.start();
            try {
                isNormalReturn = parkingOrderStatusQuery.get(5, TimeUnit.MINUTES);
            } catch (Exception e){
                isNormalReturn = false;
            }
            exitParkingRecord.setPaymentType("线上支付");
            // 线程被中断或者超时返回，并且订单没有被支付，回复不开闸
            if (!isNormalReturn && !orderService.isParkingOrderPay(orderId)){
                // 不自动开闸，人工处理
                licensePlateResultVO.setInfo("no");
                licensePlateResultVO.setPlateId(licensePlateResultDO.getPlateId());
                exitParkingRecord.setStatus(1);
                parkingService.updateParkingRecord(exitParkingRecord);
                return makeLicensePlateResultResponse(licensePlateResultVO);
            }
        }
        // 更新车辆出入记录
        exitParkingRecord.setStatus(1);
        parkingService.updateParkingRecord(exitParkingRecord);
        // 返回指令，允许开闸
        licensePlateResultVO.setInfo("ok");
        licensePlateResultVO.setPlateId(licensePlateResultDO.getPlateId());
        return makeLicensePlateResultResponse(licensePlateResultVO);
    }

    @GetMapping("/car_info/get")
    public MsgEntity getParkingCarInfo(String deviceId){
        if (deviceId == null || deviceId.isEmpty()){
            return new MsgEntity("fail", MsgEntity.FAIL, "device id is empty");
        }
        ParkingCarInfoVO parkingCarInfoVO = new ParkingCarInfoVO();
        // 根据设备ID发送TCP请求获取车辆信息，返回相应的停车订单信息
        String ip = "127.0.0.1"; // TODO 这个地方可能需要做一下ip和设备id的映射
        Map<String, Object> command = new HashMap<>();
        command.put("cmd", "trigger");
        String tcpStr = RequestUtil.doTcp(ip,StringUtil.JsonToString(command));
        JSONObject licensePlateResult = JSONObject.parseObject(tcpStr);
        LicensePlateResultDO licensePlateResultDO = parseLicensePlateResultJson(licensePlateResult);
        // 查询停车记录
        ParkingRecordQueryDO parkingRecordQueryDO = new ParkingRecordQueryDO();
        parkingRecordQueryDO.setLicense(licensePlateResultDO.getLicense());
        parkingRecordQueryDO.setVehicleState(1);
        List<ParkingRecordDO> parkingRecordDOs = parkingService.getParkingRecord(parkingRecordQueryDO);
        if (parkingRecordDOs.size() > 0){
            ParkingRecordDO parkingRecordDO = parkingRecordDOs.get(0);
            BeanUtils.copyProperties(parkingRecordDO, parkingCarInfoVO);
            // 查询订单记录
            ParkingOrderQueryDO parkingOrderQueryDO = new ParkingOrderQueryDO();
            parkingOrderQueryDO.setInoutId(parkingRecordDO.getId());
            List<ParkingOrderDO> parkingOrderDOS = orderService.getParkingOrder(parkingOrderQueryDO);
            if (parkingOrderDOS.size() > 0){
                ParkingOrderDO parkingOrderDO = parkingOrderDOS.get(0);
                BeanUtils.copyProperties(parkingCarInfoVO, parkingOrderDO);
            }
        }
        Map<String, Object> res = new HashMap<>();
        res.put("msg", parkingCarInfoVO);
        return new MsgEntity("success", MsgEntity.SUCCESS, res);
    }

    @PostMapping("/pay")
    public MsgEntity payParkingOrder(@RequestBody JSONObject params){
        // 根据传入的停车订单id生成支付订单并向前端传回支付订单相关的签名等信息
        String orderId = params.getString("orderId");
        if (orderId == null || orderId.isEmpty()){
            return new MsgEntity("fail", MsgEntity.FAIL, "order id is empty");
        }
        String wayCode = params.getString("wayCode");
        if (wayCode == null || wayCode.isEmpty()){
            return new MsgEntity("fail", MsgEntity.SUCCESS, "way code is empty");
        }
        ParkingOrderQueryDO parkingOrderQueryDO = new ParkingOrderQueryDO();
        parkingOrderQueryDO.setId(orderId);
        List<ParkingOrderDO> parkingOrderDOS = orderService.getParkingOrder(parkingOrderQueryDO);
        if (parkingOrderDOS.size() == 0 ){
            return new MsgEntity("fail", MsgEntity.FAIL, "order id is wrong , parking order is not exits");
        }
        ParkingOrderDO parkingOrderDO = parkingOrderDOS.get(0);
        parkingOrderDO.setWayCode(wayCode);
        PayOrderCommitResultDO payOrderCommitResultDO = orderService.commitParkingPayOrder(parkingOrderDO);
        Map<String, Object> res = new HashMap<>();
        res.put("msg", payOrderCommitResultDO);
        return new MsgEntity("success", MsgEntity.SUCCESS, res);
    }

    @PostMapping("/monthly_card/buy")
    public MsgEntity buyMonthCard(@RequestBody TollMonthCardOrderDTO tollMonthCardOrderDTO){
        // 创建月卡商品订单、支付订单，返回支付订单相关信息
        if (tollMonthCardOrderDTO == null){
            return new MsgEntity("fail", MsgEntity.SUCCESS, "param parse error");
        }
        TollMonthCardOrderDO tollMonthCardOrderDO = new TollMonthCardOrderDO();
        BeanUtils.copyProperties(tollMonthCardOrderDTO, tollMonthCardOrderDO);
        String orderId = orderService.createMonthCardOrder(tollMonthCardOrderDO);
        tollMonthCardOrderDO.setId(orderId);
        PayOrderCommitResultDO payOrderCommitResultDO = orderService.commitMonthCardPayOrder(tollMonthCardOrderDO);
        Map<String, Object> res = new HashMap<>();
        res.put("msg", payOrderCommitResultDO);
        return new MsgEntity("success", MsgEntity.SUCCESS, res);
    }

    private LicensePlateResultDO parseLicensePlateResultJson(JSONObject params){
        if (params == null || params.isEmpty()){
            return null;
        }
        JSONObject alarmInfoPlate = params.getJSONObject("AlarmInfoPlate");
        if (alarmInfoPlate == null || alarmInfoPlate.isEmpty()){
            return null;
        }
        LicensePlateResultDO licensePlateResultDO = new LicensePlateResultDO();
        licensePlateResultDO.setDeviceName(alarmInfoPlate.getString("deviceName"));
        licensePlateResultDO.setIpAddr(alarmInfoPlate.getString("ipaddr"));
        licensePlateResultDO.setDeviceId(alarmInfoPlate.getString("serialno"));
        JSONObject result = alarmInfoPlate.getJSONObject("result");
        /**如果result或者这个json中的plateResult字段为空，无需继续解析，直接返回就好。
         * 因为这个字段缺失，后续需要解析的字段一定是缺失的。对于缺少的字段，业务逻辑代码中再根据实际情况处理
        */
         if (result == null || alarmInfoPlate.isEmpty()){
            return  licensePlateResultDO;
        }
        JSONObject plateResult = result.getJSONObject("PlateResult");
        if (result == null || alarmInfoPlate.isEmpty()){
            return  licensePlateResultDO;
        }
        JSONObject carBrand = plateResult.getJSONObject("car_brand");
        if (carBrand != null && !carBrand.isEmpty()){
            licensePlateResultDO.setVehicleType(carBrand.getInteger("type"));
        }
        String imagePath = plateResult.getString("imagePath");
        if (imagePath != null && !imagePath.isEmpty()){
            String snapImageUrl = String.format("http://%s:8080%s", alarmInfoPlate.getString("ipaddr"), imagePath);
            licensePlateResultDO.setSnapImageUrl(snapImageUrl);
        }
        licensePlateResultDO.setIsFakePlate(plateResult.getInteger("is_fake_plate"));
        licensePlateResultDO.setPlateId(plateResult.getString("plateid"));
        licensePlateResultDO.setLicense(plateResult.getString("license"));
        licensePlateResultDO.setReceivedTime(CommonUtil.getCurrentTime());
        return licensePlateResultDO;
    }

    private JSONObject makeLicensePlateResultResponse(LicensePlateResultVO licensePlateResultVO){
        JSONObject response = new JSONObject();
        JSONObject responseAlarmInfoPlate = new JSONObject();
        responseAlarmInfoPlate.put("info", licensePlateResultVO.getInfo());
        responseAlarmInfoPlate.put("plateid", licensePlateResultVO.getPlateId());
        responseAlarmInfoPlate.put("is_pay", licensePlateResultVO.getIsPay());
        response.put("Response_AlarmInfoPlate", responseAlarmInfoPlate);
        return response;
    }
}